/*!
 * Copyright (C) 2020 - All Rights Reserved by
 * @author : ZhaoYanbo
 * @email  : zyb920@hotmail.com
 * @created: 2020-10-31
 * @version: 1.0.0.0
 *
 */

#include "lyriceditwidget.h"
#include <QtDebug>
#include <QPainter>
#include <QMouseEvent>
#include "QCoreApplication"

LyricEditWidget::LyricEditWidget(QWidget *parent) : QWidget(parent)
{
    this->setProperty("min_w", 120);
    p_ruler   = new LE_Ruler;
    p_invoker = new LE_CommandInvok;
    m_sy = 140;
    m_scaleMode = false;
    m_prePreviewIndex = -1;

    this->setMouseTracking(true);

    QFont font = this->font();
    font.setPixelSize(48);
    this->setFont(font);

    m_lineHeight = 120;
    m_showMode   = FineShowMode::NormalShow;
}

LyricEditWidget::~LyricEditWidget()
{
    delete p_ruler;
    p_ruler = nullptr;

    delete p_invoker;
    p_invoker = nullptr;
}

void LyricEditWidget::setShowMode(FineShowMode mode)
{
    m_showMode = mode;

    update();
}

void LyricEditWidget::setShowString(const QString &str)
{
    p_invoker->clear();

    //重置基础信息
    m_markPic         = QPixmap();
    m_pressed         = false;
    m_selectedIndex   = -1;
    m_curX            = -1;

    //去掉空格
    m_origiStr = str.trimmed();
    m_str = QString(str).replace(' ', "");

    m_linePos.clear();

    const int str_len = m_str.length();
    if(str_len < 1)
        return;

    for(int i=0; i <= str_len; ++i)
    {
        ZPos pos;
        pos.x = 40 + 60 * i;
        pos.normal = true;
        m_linePos.append(pos);
    }

    m_linePos.first().canMove = true;
    m_linePos.last().canMove  = true;
    this->setProperty("min_w", m_linePos.last().x + 120);

    update();
}

void LyricEditWidget::openScaleMode(bool b)
{
    m_scaleMode = b;
}

bool LyricEditWidget::loadFromValues(const QVector<VPos> &v_points)
{
    if(v_points.length() < 1)
        return false;

    float vspace = p_ruler->curSpaceValue();
    float v1 = v_points[0].value - vspace;
    if(v1 < 0.001f)
        v1 = 0.00f;
    p_ruler->setCurStartValue(v1);

    int tmpX;
    QVector<ZPos> z_points;
    for(const VPos &v : v_points)
    {
        ZPos pos;
        pos.normal  = v.normal;
        pos.canMove = v.canMove;
        pos.previewHere = v.previewHere;

        tmpX = p_ruler->value2pos(v.value);
        pos.x       = tmpX;

        z_points.append(pos);
    }
    int minWidth = p_ruler->value2pos(v_points.last().value + vspace);
    this->setProperty("min_w", minWidth);

    updateSize(minWidth);
    updateRuler();

    m_linePos.clear();
    m_linePos << z_points;
    update();

    return true;
}

bool LyricEditWidget::loadFromPoints(const QVector<ZPos> &points)
{
    if(points.length() < 1)
        return false;

    m_linePos.clear();
    m_linePos << points;
    update();

    return true;
}

void LyricEditWidget::zoomIn()
{
    if( !p_ruler->canZoomIn() )
        return;

    LE_ZoomCommand *command = new LE_ZoomCommand(true, this);
    p_invoker->push(command);
}

void LyricEditWidget::zoomOut()
{
    if( !p_ruler->canZoomOut() )
        return;

    LE_ZoomCommand *command = new LE_ZoomCommand(false, this);
    p_invoker->push(command);
}

void LyricEditWidget::zoomInCommand()
{
    if( !p_ruler->canZoomIn() )
        return;

    //缩放之前获取当前的值
    QVector<VPos> vPoints;
    for(const auto &pos : m_linePos)
    {
        VPos vPos(0.0f);
        vPos.canMove = pos.canMove;
        vPos.normal  = pos.normal;
        vPos.previewHere = pos.previewHere;
        vPos.value = p_ruler->pos2value(pos.x);

        vPoints.append(vPos);
    }

    p_ruler->zoomIn();

    loadFromValues(vPoints);
    update();
}

void LyricEditWidget::zoomOutCommand()
{
    if( !p_ruler->canZoomOut() )
        return;

    //缩放之前获取当前的值
    QVector<VPos> vPoints;
    for(const auto &pos : m_linePos)
    {
        VPos vPos(0.0f);
        vPos.canMove = pos.canMove;
        vPos.normal  = pos.normal;
        vPos.previewHere = pos.previewHere;
        vPos.value = p_ruler->pos2value(pos.x);
        vPoints.append(vPos);
    }

    p_ruler->zoomOut();

    loadFromValues(vPoints);
    update();
}

bool LyricEditWidget::canMove(int index) const
{
    if( !isValid(index) )
        return false;

    return m_linePos[index].canMove;
}

bool LyricEditWidget::invertPreview(int index)
{
    if( !isValid(index) )
        return false;

    m_linePos[index].invertPreview();
    update();

    return true;
}

bool LyricEditWidget::doClickCanMove(int index)
{
    if( !isValid(index) )
        return false;

    m_linePos[index].invertMove();
    if(m_linePos[index].canMove)
    {
        //插入非normal线
        ZPos t_pos;
        t_pos.normal = false;
        t_pos.canMove = true;
        t_pos.x = m_linePos[index].x;

        m_linePos.insert(index, t_pos);
    }
    else
    {
        //移除非normal线
        if(index >= 1)
        {
            m_linePos.removeAt(index - 1);
        }
    }
    update();
    return true;
}

bool LyricEditWidget::doClickPreview(int index)
{
    bool b = false;

    if( isValid(index) )
        b = m_linePos[index].previewHere;

    //清除上一个标记(上一个被标记.如果点击canmove,可能导致索引变化)
    for(auto & pos : m_linePos)
        pos.previewHere = false;

    if( isValid(index) )
        m_linePos[index].previewHere = !b;

    update();

    return true;
}

void LyricEditWidget::updateSize(int w)
{
    int minWidth = w;
    if(minWidth < 1)
        minWidth = this->property("min_w").toInt();

    if(this->parentWidget())
    {
        if(minWidth < this->parentWidget()->width())
        {
            this->resize(this->parentWidget()->width(), this->height());
        }
        else
            this->resize(minWidth, this->height());
    }
    else
        this->resize(minWidth, this->height());
}

QVector<VPos> LyricEditWidget::points2values(const QVector<ZPos> &points) const
{
    int i=0;
    QVector<VPos> vPoints(points.length());
    for(const auto &pos : points)
    {
        VPos vPos(0.0f);
        vPos.canMove = pos.canMove;
        vPos.normal  = pos.normal;
        vPos.previewHere = pos.previewHere;
        vPos.value = p_ruler->pos2value(pos.x);
        vPoints[i++] = vPos;
    }
    return vPoints;
}

int LyricEditWidget::checkCursor(const QPoint &qpos) const
{
    int index = -1;
    if(m_showMode != FineShowMode::NormalShow)
    {
        int len = m_linePos.length();
        for(int i=0; i<len; ++i)
        {
            const ZPos &pos = m_linePos[i];
            if(pos.normal)
            {
                if(std::abs(qpos.x() - pos.x) < 4 &&
                        qpos.y() >= m_sy && qpos.y() <= (m_sy + m_lineHeight))
                {
                    index = i;
                    break;
                }
            }
            else //非normal线包含外面延长部分
            {
                if(std::abs(qpos.x() - pos.x) < 4 &&
                        qpos.y() >= m_sy + m_lineHeight && qpos.y() <= (m_sy + m_lineHeight * 2))
                {
                    index = i;
                    break;
                }
            }
        }
    }
    else
    {
        const ZPos &pos1 = m_linePos.first();
        if(std::abs(qpos.x() - pos1.x) < 4 &&
                qpos.y() >= m_sy && qpos.y() <= (m_sy + m_lineHeight))
            index = 0;

        if(index == -1)
        {
            const ZPos &pos2 = m_linePos.last();
            if(std::abs(qpos.x() - pos2.x) < 4 &&
                    qpos.y() >= m_sy && qpos.y() <= (m_sy + m_lineHeight))
                index = m_linePos.length() - 1;
        }
    }
    if(index == -1)
    {
        const ZPos &pos1 = m_linePos.first();
        const ZPos &pos2 = m_linePos.last();
        QRect rect(pos1.x, m_sy, pos2.x-pos1.x, m_lineHeight);
        //判断是否点击在矩形区域内,矩形区域内部可以进行整体移动
        if(rect.contains(qpos))
            return -2;
    }
    return index;
}

int LyricEditWidget::doClickMoveRect(const QPoint &qpos) const
{
    int index = -1;
    int len = m_linePos.length();
    for(int i=1; i<len-1; ++i)
    {
        const ZPos &pos = m_linePos[i];
        if(pos.normal && canMoveRect(pos).contains(qpos))
        {
            index = i;
            break;
        }
    }
    return index;
}

int LyricEditWidget::doClickPreview(const QPoint &qpos) const
{
    int index = -1;
    int len = m_linePos.length();
    for(int i=1; i<len-1; ++i)
    {
        const ZPos &pos = m_linePos[i];
        if(pos.normal && previewRect(pos).contains(qpos))
        {
            index = i;
            break;
        }
    }
    return index;
}

QRect LyricEditWidget::canMoveRect(const ZPos &pos) const
{
    const int w = 16;
    return QRect(pos.x - w/2, m_sy - w*3/2, w, w);
}

QRect LyricEditWidget::previewRect(const ZPos &pos) const
{
    const int w = 16;
    return QRect(pos.x - w/2, m_sy + m_lineHeight+w/2, w, w);
}

bool LyricEditWidget::doHoverMove(const QPoint &pos)
{
    int index = -1;

    if(m_showMode != FineShowMode::NormalShow)
    {
        index = doClickMoveRect(pos);
        if(index > 0)
        {
            this->setCursor(Qt::PointingHandCursor);//手指样式
            return true;
        }

        index = doClickPreview(pos);
        if(index > 0)
        {
            this->setCursor(Qt::PointingHandCursor);//手指样式
            return true;
        }
    }

    index = checkCursor(pos);
    if(index == -2)
    {
        this->setCursor(Qt::SizeAllCursor);//移动样式
    }
    else if(index > -1)
    {
        if(m_linePos[index].canMove)
            this->setCursor(Qt::SizeHorCursor);//垂直样式
        else
            this->setCursor(Qt::SizeAllCursor);//移动样式
    }
    else
    {
        this->unsetCursor();
        return false;
    }
    return true;
}

bool LyricEditWidget::doMouseMove(int x)
{
    const int curIndex = m_selectedIndex;
    if(curIndex == -1) //点击的外部  不做移动操作
    {
        m_curX = x;
        update();
        return false;
    }

    int len = m_linePos.length();
    QVector<ZPos> tmpPos;
    tmpPos << m_origiLinePos;

    if(curIndex == -2) //选中局部,整体移动
    {
        int delta = x - m_pressedPos.x();

        //禁止移出左边范围
        int deltaX  = m_origiLinePos[0].x + delta;
        int deltaX2 = m_origiLinePos.last().x + delta;
        if(deltaX < 0)
        {
            p_ruler->doMove(deltaX);
            updateRuler();

            delta = 0 - m_origiLinePos[0].x;
        }
        else if(deltaX2 > this->width())//禁止移出右边范围
        {
            p_ruler->doMove(deltaX2 - this->width());
            updateRuler();
            delta = this->width() - m_origiLinePos.last().x;
        }
        else
        {
            if(p_ruler->doMove())//防止重复绘制无用功
                updateRuler();
        }

        for(int i=0;i<len; ++i)
        {
            tmpPos[i].x = (m_origiLinePos[i].x + delta);
        }

        m_linePos.clear();
        m_linePos << tmpPos;

        return true;
    }

    if(curIndex > 0)
    {
        int tmpCurIndex = curIndex;//辅助,如果是中间canmove,与normal之间不能进行缩放
#if 1
        //找到上一个canmove索引, 中间区域 整体缩放
        if(curIndex > 1)
        {
            int _x = x;
            if(curIndex != len-1 && m_origiLinePos[curIndex].normal)
            {
                tmpCurIndex = curIndex - 1;
                _x   = x - (m_origiLinePos[tmpCurIndex + 1].x - m_origiLinePos[tmpCurIndex].x);
            }

            if(m_scaleMode)
            {
                int preIndex = 0;
                for(int i=tmpCurIndex-1;i>0;--i)
                {
                    if(m_origiLinePos[i].normal && m_origiLinePos[i].canMove)
                    {
                        preIndex = i;
                        break;
                    }
                }
                int _old = m_origiLinePos[tmpCurIndex].x - m_origiLinePos[preIndex].x;
                int _new = _x - m_origiLinePos[preIndex].x;
                //移动非normal时,防止超过后面的坐标
                if(!m_origiLinePos[tmpCurIndex].normal && tmpCurIndex == curIndex)
                {
                    if(_x >= m_origiLinePos[tmpCurIndex + 1].x)
                        _new = m_origiLinePos[tmpCurIndex + 1].x - m_origiLinePos[preIndex].x;
                }

                float scale = _new * 1.0f / _old;
                int newX = 0;
                //前面部分整体缩放
                for(int i=preIndex+1;i<tmpCurIndex; ++i)
                {
                    newX = m_origiLinePos[preIndex].x +
                            (m_origiLinePos[i].x - m_origiLinePos[preIndex].x) * scale;
                    if(newX <= tmpPos[i-1].x + 16)
                        scale = (tmpPos[i-1].x - m_origiLinePos[preIndex].x + 16) * 1.0f /
                                (m_origiLinePos[i].x - m_origiLinePos[preIndex].x);
                    tmpPos[i].x = m_origiLinePos[preIndex].x +
                            (m_origiLinePos[i].x - m_origiLinePos[preIndex].x) * scale;
                }
            }
        }
#endif

        int delta = x - m_pressedPos.x();
        //判断左移动时 禁止越过上一个出现异常
        if(m_origiLinePos[tmpCurIndex].x + delta <= tmpPos[tmpCurIndex-1].x + 16)
            delta = tmpPos[tmpCurIndex-1].x + 16 - m_origiLinePos[tmpCurIndex].x;

        if(tmpCurIndex == curIndex)//点的非normal线
        {
            //如果不是常规线  不能超过后面的坐标
            if( !m_origiLinePos[tmpCurIndex].normal )
            {
                if(m_origiLinePos[tmpCurIndex].x + delta >= tmpPos[tmpCurIndex+1].x)
                    delta = tmpPos[tmpCurIndex+1].x - m_origiLinePos[tmpCurIndex].x;
            }
            tmpPos[tmpCurIndex].x = (m_origiLinePos[tmpCurIndex].x + delta);
        }
        else
        {
            //偏移后面的坐标
            for(int i=tmpCurIndex;i<len; ++i)
            {
                tmpPos[i].x = (m_origiLinePos[i].x + delta);
            }
        }


        m_linePos.clear();
        m_linePos << tmpPos;

        //更改大小
        if(m_linePos.last().x > this->width())
        {
            this->resize(m_linePos.last().x + 120, this->height());
        }

        return true;
    }

    //移动最左边的这根线
    if(curIndex == 0)
    {
#if 1
        if(m_scaleMode)
        {
            int nextIndex = len-1;
            for(int i=1;i<len;++i)
            {
                if(!m_origiLinePos[i].normal)
                {
                    nextIndex = i;
                    break;
                }
                else if(m_origiLinePos[i].canMove)
                {
                    nextIndex = i;
                    break;
                }
            }
            int _old = m_origiLinePos[nextIndex].x - m_origiLinePos[0].x;
            int _new = m_origiLinePos[nextIndex].x - x;
            if(x <= 0)
                _new = m_origiLinePos[nextIndex].x;
            float scale = _new * 1.0f / _old;
            int newX = 0;

            for(int i=nextIndex-1; i>0; --i)
            {
                newX = m_origiLinePos[nextIndex].x -
                        (m_origiLinePos[nextIndex].x - m_origiLinePos[i].x) * scale;
                if(newX > tmpPos[i+1].x - 16)
                    scale = (tmpPos[i+1].x - 16 - m_origiLinePos[nextIndex].x) * 1.0f /
                            (m_origiLinePos[i].x - m_origiLinePos[nextIndex].x);
                tmpPos[i].x = m_origiLinePos[nextIndex].x -
                        (m_origiLinePos[nextIndex].x - m_origiLinePos[i].x) * scale;
            }
        }
#endif
        int delta = x - m_pressedPos.x();

        //判断左移动时 禁止越过上一个出现异常
        if(m_origiLinePos[0].x + delta <= 1)
            delta = 1 - m_origiLinePos[0].x;

        //右移动时 不能超过右边这根线
        if(m_origiLinePos[0].x + delta >= tmpPos[1].x - 16)
            delta = tmpPos[1].x - m_origiLinePos[0].x - 16;

        tmpPos[0].x = (m_origiLinePos[0].x + delta);

        m_linePos.clear();
        m_linePos << tmpPos;

    }

    return true;
}

bool LyricEditWidget::doMousePress(const QPoint &pos)
{
    int index = -1;
    if(m_showMode != FineShowMode::NormalShow)
    {
        index = doClickMoveRect(pos);
        if(index > 0)
        {
            //如果是取消canmove  先把前面的线移动到当前位置
            if(m_linePos[index].canMove && (m_linePos[index].x != m_linePos[index-1].x))
            {
                //先移动到初始位置
                m_origiLinePos.clear();
                m_origiLinePos << m_linePos;


                m_pressedPos = QPoint(m_linePos[index-1].x, m_sy);
                m_selectedIndex = index - 1;
                doMouseMove(m_linePos[index].x);
                if(m_selectedIndex != -1)
                {
                    LE_MoveCommand *command = new LE_MoveCommand(points2values(m_origiLinePos),
                                                                 points2values(m_linePos), this);
                    p_invoker->push(command);
                }
                m_pressed = false;
                m_selectedIndex = -1;
                m_pressedPos = QPoint();
            }

            //
            LE_CanMoveCommand *command = new LE_CanMoveCommand(index, this);
            p_invoker->push(command);
            //doClickCanMove(index);
            return true;
        }

        index = doClickPreview(pos);
        if(index > 0)
        {
            LE_PreviewCommand *command = new LE_PreviewCommand(m_prePreviewIndex,
                                                               index, this);
            p_invoker->push(command);
            //doClickPreview(index);
            m_prePreviewIndex = index;
            return true;
        }
    }

    m_pressed = true;
    index = checkCursor(pos);
    if(index == -1)
    {
        m_curX = pos.x();
        update();
        return false;
    }

    m_pressedPos = pos;
    m_selectedIndex = index;

    //不能canmove时 移动全局
    if(index > -1)
    {
        if( !m_linePos[index].canMove )
            m_selectedIndex = -2;
    }

    m_origiLinePos.clear();
    m_origiLinePos << m_linePos;

    m_origiLineValus.clear();
    m_origiLineValus.append( points2values(m_linePos) );

    return true;
}

bool LyricEditWidget::isValid(int index) const
{
    const int len = m_linePos.length();
    if(index < 0 || index >= len)
        return false;
    return true;
}

void LyricEditWidget::updateRuler()
{
    if(p_ruler)
        m_markPic = p_ruler->update(this->width(), 20);
}

void LyricEditWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);
    p.setRenderHint(QPainter::TextAntialiasing);
    p.setRenderHint(QPainter::SmoothPixmapTransform);

    p.fillRect(this->rect(), "#303136");

    if(m_linePos.length() < 2)
        return;

    const int len = m_linePos.length();

    QPen pen = p.pen();
    pen.setWidth(2);
    pen.setColor("#545556");
    p.setPen(pen);

    QFont font = p.font();

    //绘制详细信息
    if(m_showMode != FineShowMode::NormalShow)
    {
        p.save();
        p.setPen(Qt::white);
        font.setPixelSize(20);
        p.setFont(font);

        QString info;
        float startValue = p_ruler->pos2value( m_linePos.first().x );
        float endValue   = p_ruler->pos2value( m_linePos.last().x );
        info.append( QString("(%1,%2)-").arg(startValue, 0, 'f', 2).arg(endValue, 0, 'f', 2) );

        int spaceCount = 0;//记录空格个数
        int wave = 0;//处理canmove时插入了非normal线,导致index变化
        QChar tmpChar;
        for(int i=0;i<len-1;++i)
        {
            tmpChar = m_origiStr.at(i-wave + spaceCount);
            while(tmpChar == ' ')
            {
                ++spaceCount;
                info.append( tmpChar );
                tmpChar = m_origiStr.at(i-wave + spaceCount);
            }

            const ZPos &pos = m_linePos[i];
            if(!pos.normal)
            {
                ++wave;
                float value = p_ruler->pos2value( pos.x );
                if(pos.x == m_linePos[i+1].x)
                {
                    info.append( QString("<%1>").arg(value, 0, 'f', 2) );
                }
                else
                {
                    float value2 = p_ruler->pos2value( m_linePos[i+1].x ) - value;
                    info.append( QString("<%1+%2>").arg(value, 0, 'f', 2).arg(value2, 0, 'f', 2) );
                }
                continue;
            }
            info.append( m_origiStr.at(i-wave + spaceCount) );
        }
        p.drawText(0,0,this->width(), 80, Qt::AlignCenter | Qt::TextWrapAnywhere, info);
        p.restore();
    }


    //绘制刻度
    if( !m_markPic.isNull() )
        p.drawPixmap(0, 80, m_markPic);

    //绘制上横线  下横线
    ZPos first = m_linePos.first();
    ZPos last = m_linePos.last();
    p.fillRect(QRect(first.x, m_sy, last.x-first.x, m_lineHeight), "#212125");
    p.drawLine(first.x, m_sy, last.x, m_sy);
    p.drawLine(first.x, m_sy + m_lineHeight,
               last.x,  m_sy + m_lineHeight);

    //绘制文字
    p.save();
    pen.setColor("#C0C0C0");
    p.setPen(pen);
    switch (m_showMode) {
    case FineShowMode::NormalShow:
    {
        const ZPos &pos1 = m_linePos.first();
        const ZPos &pos2 = m_linePos.last();
        p.drawText(QRect(pos1.x, m_sy, pos2.x-pos1.x,m_lineHeight),
                   Qt::AlignCenter,
                   m_origiStr);
        break;
    }
    case FineShowMode::KaraokeShow:
    {
        int wave = 0;//处理canmove时插入了非normal线,导致index变化
        for(int i=1; i<len; ++i)
        {
            const ZPos &pos = m_linePos[i-1];
            if(!pos.normal)
            {
                ++wave;
                continue;
            }

            QRect r(pos.x, m_sy, m_linePos[i].x - pos.x, m_lineHeight);
            p.drawText(r, Qt::AlignCenter, m_str.at(i-wave-1));
        }
        break;
    }
    default:
        break;
    }
    p.restore();

    //绘制间隔区域
    p.save();
    pen.setColor("#FFFFFF");
    p.setPen(pen);
    font.setPixelSize(16);
    p.setFont(font);
    for(int i=1;i<len;++i)
    {
        const ZPos &pos = m_linePos[i];
        if(!pos.normal)
        {
            const ZPos &pos1 = m_linePos[i + 1];
            QRect rect(pos.x, m_sy + 12, pos1.x-pos.x, m_lineHeight - 12 * 2);

            if(rect.width() >= 4 )
                p.fillRect(rect, QBrush("#303136") );

            if(rect.width() >= 8) // <8文字不全
            {
                float v1 = p_ruler->pos2value(pos1.x);
                float v2 = p_ruler->pos2value(pos.x);
                float v = v1 - v2;
                p.drawText(rect, Qt::TextWrapAnywhere | Qt::AlignCenter, "+"+QString::number(v, 'f', 2));
            }
        }
    }
    p.restore();


    //绘制竖线
    pen.setColor("#545556");
    if(m_showMode != FineShowMode::NormalShow)
    {
        for(const ZPos &pos : m_linePos)
        {
            p.save();
            if(pos.normal)
                pen.setStyle(Qt::SolidLine);
            else
                pen.setStyle(Qt::DotLine);
            p.setPen(pen);
            p.drawLine(pos.x, m_sy, pos.x, m_sy + m_lineHeight);
            p.restore();
        }
    }
    else
    {
        p.save();
        pen.setStyle(Qt::SolidLine);
        p.setPen(pen);
        const ZPos &pos1 = m_linePos.first();
        const ZPos &pos2 = m_linePos.last();
        p.drawLine(pos1.x, m_sy,
                   pos1.x, m_sy + m_lineHeight);
        p.drawLine(pos2.x, m_sy,
                   pos2.x, m_sy + m_lineHeight);
        p.restore();

    }
    //绘制可移动框  preview圆点
    if(m_showMode != FineShowMode::NormalShow)
    {
        for(int i=1; i<len-1; ++i)
        {
            const ZPos &pos = m_linePos[i];

            if(pos.normal)
            {
                //绘制can move
                p.save();
                if(pos.canMove)
                {
                    p.setBrush(QColor("#007EC8") );
                }

                p.drawRect(canMoveRect(pos));
                p.restore();

                //绘制preview
                p.save();
                if(pos.previewHere)
                    p.setBrush(QColor("#C80000") );
                else
                    p.setBrush(QColor("#303136") );
                p.drawEllipse(previewRect(pos));
                p.restore();
            }
            else
            {
                p.drawLine(pos.x, m_sy + m_lineHeight,
                           pos.x, m_sy + m_lineHeight * 2);
            }
        }
    }

    p.save();
    pen.setColor("#F37B03");
    p.setPen(pen);
    p.drawLine(m_curX, 0, m_curX, this->height());
    p.restore();
}

void LyricEditWidget::mousePressEvent(QMouseEvent *e)
{
    e->accept();
    p_ruler->doMoveStart();
    doMousePress( e->pos() );
}

void LyricEditWidget::mouseMoveEvent(QMouseEvent *e)
{
    e->accept();
    if( !m_pressed )
        doHoverMove( e->pos() );
    else {
        doMouseMove( e->pos().x() );
        update();
    }
}

void LyricEditWidget::mouseReleaseEvent(QMouseEvent *e)
{
    e->accept();
    p_ruler->doMoveEnd();
    if(m_selectedIndex != -1)
    {
        LE_MoveCommand *command = new LE_MoveCommand(m_origiLineValus,
                                                     points2values(m_linePos), this);
        p_invoker->push(command);
    }
    //更改大小
    this->setProperty("min_w", m_linePos.last().x + 120);
    int minWidth = this->property("min_w").toInt();

    updateSize(minWidth);

    if(m_linePos.last().x > minWidth)
    {
        this->resize(m_linePos.last().x + 120, this->height());
    }

    m_pressed = false;
    m_selectedIndex = -1;
    m_pressedPos = QPoint();
}

void LyricEditWidget::resizeEvent(QResizeEvent *e)
{
    const QSize new_size = e->size();

    if(new_size.width() > 1 && new_size.height() > 1)
    {
        updateRuler();
    }
    e->accept();
    QWidget::resizeEvent(e);
}
